<?php
/**
 * @author 3Code Group 
 * @author Pawel Giemza
 * @version 1.0
 * @package Arrow
 * @subpackage Model
 * @link http://arrowplatform.org/
 * @copyright 2009 3code 
 * @license MIT
 * 
 * @date 2009-12-01 
*/

ArrowController::importModel("org.arrowplatform.model.ArrowModelIterator");
ArrowController::importModel("org.arrowplatform.model.ArrowDatasetRow");
class ArrowDataset implements Iterator, ArrayAccess, Countable{	
	private $rows = array();
	private $objects = array();	
	private $datasetCache = array();
	public $namesDictionary = array();
	
	
	public function __construct($data, $related = array()){
			if (empty($data))
				return;
		
			if ($data instanceof ArrowDataset){
				//TODO : this condition has been added for compatibility purposes 
				$this->rows = $data->rows;
				$this->objects = $data->objects;
				$this->datasetCache = $data->datasetCache;
				//throw new ArrowException('dataset in dataset');
				return;
			}
					
			//list all classes used in dataset 
			$dat = $data[0];
			$classes = array();
			$baseClass = null;
			foreach ($dat as $key=>$obj ){
				$classes[$key] = $key;
				if ($baseClass === null)
					$baseClass = $key;
			}			
			$allConf = ArrowOrmConfig::getClassConf();
	
			//perform object caching
			foreach ($data as $rowKey=>$row)
				foreach ($row as $className=>$classData){
					$addClass = explode('[',$className);
					$addClass = $addClass[0];
					$keyName = ArrowOrmConfig::getKeyName($addClass);
					if (isset($classData[$keyName]) && !empty($classData[$keyName]) ){
						$key = $classData[$keyName];					
						if (isset($this->datasetCache[$addClass][$key]))
							$data[$rowKey][$className] = $this->datasetCache[$addClass][$key];
						else{
							$this->datasetCache[$addClass][$key] = ArrowOrmPersistent::datasetConstruct($classData, $addClass);
							$data[$rowKey][$className] = $this->datasetCache[$addClass][$key];
						}
					}
			}
			$this->rows = $data;
			//objects available through array access
			foreach ($this->datasetCache[reset($classes)] as $obj){
				$this->objects[] = $obj;
			}
			//add related objects
			$loopcount = 0;
			$main = true;
			foreach ($this->rows as $rowKey=>&$row){
				
				
				foreach ($row as $className=>&$classObj){
					if($rowKey == 0){
						if(is_object($classObj))
							$keys = $classObj->getCurrentFieldnames();
						else 
							$keys = array_keys($classObj);
						foreach( $keys as $key){
							if($main)
								$this->namesDictionary[$key] = array( $className, $key );
								
							$this->namesDictionary[$className.":".$key] = array( $className, $key );
						}
						$main = false;
					}
					
					$test = strpos($className, "[");
					$relatedClass = null;
					if( $test !== false){
						$test2  = strpos($className, "::");
						if($test2 !== false)
							$relatedClass = substr($className, $test, $test2 - $test);
						$addClass = strpos( $className, 0, $test); 
					}else
						$addClass = $className;
						
					if ($relatedClass === null)
						$relatedClasses = $related[$addClass];
					else
						$relatedClasses = array($relatedClass); //for Dictionary (TODO: at least I think so :) )
					foreach ($relatedClasses as $relClass){
						if (isset($this->rows[$rowKey][$relClass])){
							//not all relations are used in every join so check if object exists
							$obj = $this->rows[$rowKey][$relClass];
							if (is_object($obj) && is_object($this->rows[$rowKey][$className]) )
								$obj->addRelated($this->rows[$rowKey][$className]/*['id'] //usefull for debug */,$addClass);
						}
					}
				}
			}
		
		// convert to dataset rows
		$new_rows = array(); 
		foreach ($this->rows as $key => &$row){
			$new_rows[] = new ArrowDatasetRow($row, $this);
		}
		$this->rows = $new_rows;
				
	}
	
//------------------------------------------------------------------

	public function getBasicObjects(){
		return $this->objects;
	}
	
//------------------------------------------------------------------	
	
	public function rewind() {
		reset($this->rows);
	}

	public function current() {
			return current($this->rows);
	}

	public function key() {
		return key($this->rows);
	}

	public function next() {
		$var = next($this->rows);

	}

	public function valid() {
		if( current($this->rows) )
			return true;
		return false ;  		
	}
	//-----------------Countable --------------------------------
	public function count(){
		return count($this->rows);
	}
	
	//----------------- Array Access ----------------------------
	public function offsetExists($offset){
		if (isset($this->rows[$offset])){
			return true;
		} 
		return false;
	}
	
	public function offsetSet($offset,$value){
		throw new ArrowException('Its not possible to set field values while using ArrowDataset');
	}
	
	public function offsetGet($offset){
		if (isset($this->rows[$offset])){
			return $this->rows[$offset];			
		} 
		else{
			throw new ArrowException("Offset {$offset} not available in ArrowDataset ",0);
		}
	}
	
	public function offsetUnset($offset){
		throw new ArrowException('Its not possible to unset field while using ArrowDataset');
	}	
	
	public function dump($print=true){
    $ret='';
    foreach ($this->rows as $key=>$row){
      $headers = false;
      if (empty($ret)) $headers = true;
      $ret .= $row->dump(false,$headers);
        //remove </table> sent by dataset row
      if ($headers) $ret = str_replace('</table>','',$ret);
    }
    $ret.='</table>';
    if ($print)
      print_r($ret);
    else
      return $ret;
	}
	
}
?>